package com.sdkj.dspservice.modules.report.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sdkj.dspservice.common.base.service.impl.CrudServiceImpl;
import com.sdkj.dspservice.common.config.Global;
import com.sdkj.dspservice.common.react.AntdProResult;
import com.sdkj.dspservice.common.utils.DateUtils;
import com.sdkj.dspservice.common.utils.StringUtils;
import com.sdkj.dspservice.modules.report.dao.ReportDao;
import com.sdkj.dspservice.modules.report.dao.SourceDao;
import com.sdkj.dspservice.modules.report.dao.TableConfigColumnDao;
import com.sdkj.dspservice.modules.report.dao.TableConfigDao;
import com.sdkj.dspservice.modules.report.entity.Report;
import com.sdkj.dspservice.modules.report.entity.Source;
import com.sdkj.dspservice.modules.report.entity.TableConfig;
import com.sdkj.dspservice.modules.report.entity.TableConfigColumn;
import com.sdkj.dspservice.modules.report.entity.tem.PaginateWithQueryColumns;
import com.sdkj.dspservice.modules.report.service.ReportService;
import com.sdkj.dspservice.modules.report.utils.SqlUtils;
import com.sdkj.dspservice.modules.report.utils.entity.JdbcSourceInfo;
import com.sdkj.dspservice.modules.report.utils.hive.HiveUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.LinkedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 报表service实现类
 *
 * @author tm
 */
@Slf4j
@Service
@Transactional(readOnly = true)
public class ReportServiceImpl extends CrudServiceImpl<ReportDao, Report> implements ReportService {

    @Autowired
    private TableConfigDao tableConfigDao;
    @Autowired
    private TableConfigColumnDao tableConfigColumnDao;
    @Autowired
    private SourceDao sourceDao;
    @Autowired
    private SqlUtils sqlUtils;

    @Override
    @Transactional(readOnly = false)
    public boolean saveOrUpdate(Report report) {
        if (report.isNewRecord()) {
            if (report.getSeeNumber() == null) {
                report.setSeeNumber(0);
            }
            if (report.getGoodNumber() == null) {
                report.setGoodNumber(0);
            }
        }
        return super.saveOrUpdate(report);
    }

    /**
     * 执行sql
     *
     * @param paramMap
     * @return
     * @throws SQLException
     */
    @Override
    public AntdProResult executeSql(Map<String, Object> paramMap) throws SQLException {
        System.out.println("进executeSql:" + paramMap);
        AntdProResult result = new AntdProResult();
        // 获取参数
        String tableConfigId = String.valueOf(paramMap.get("tableConfigId"));
        // 获取分页参数
        int current = Integer.parseInt(String.valueOf(paramMap.get("current")));
        int pageSize = Integer.parseInt(String.valueOf(paramMap.get("pageSize")));
        // 获取表配置详情
        TableConfig tableConfig = tableConfigDao.selectById(new TableConfig(tableConfigId));
        // 获取数据源配置
        Source source = sourceDao.selectById(tableConfig.getSourceId());
        // 获取表字段配置
        TableConfigColumn searchTableConfigColumn = new TableConfigColumn();
        searchTableConfigColumn.setTableConfigId(tableConfig.getId());
        List<TableConfigColumn> tableConfigColumnList = tableConfigColumnDao.selectList(new QueryWrapper<>(searchTableConfigColumn));
        // 制作字段sqlString
        String columnsString = tableConfigColumnList.stream().filter(column -> Global.YES.equals(column.getIsShow())).map(TableConfigColumn::getColumnName).collect(Collectors.joining(","));
        // sql编辑
        String sql = "select " + columnsString + " from " + tableConfig.getTableName();
        // 添加筛选
        StringBuffer conditionSql = new StringBuffer("");
        System.out.println("paramMap.size:" + paramMap.size());
        if (paramMap.size() > 3) {
            for (String key : paramMap.keySet()) {
                if (!StringUtils.inString(key, "current", "pageSize", "tableConfigId", "isDay")) {
                    // 获取value
                    Object value = paramMap.get(key);
                    // 编辑筛选
                    if (conditionSql.length() == 0) {
                        conditionSql.append(" where ");
                    } else {
                        conditionSql.append(" and ");
                    }
                    // 如果是Collection说明为区间筛选
                    System.out.println("key:" + key);
                    System.out.println(value);
                    if (value instanceof ArrayList) {
                        List<String> list = (List<String>) value;
                        if (Source.DATABASE_TYPE_HIVE.equals(source.getDatabaseType())) {
                            conditionSql.append(key + " >= " + "'" + DateUtils.utcDateStringFormat(list.get(0), "yyyyMMdd") + "' and ");
                        } else {
                            conditionSql.append(key + " >= " + "'" + DateUtils.utcDateStringFormat(list.get(0), "time".equals(key) ? "yyyyMMdd" : "yyyy-MM-dd HH:mm:ss") + "' and ");
                        }
                        // 小于等于10位，说明没有时分秒（不小于8的原因是，防止带-）
                        if (list.get(0).length() <= 10) {
                            // hive时间不一样的用法
                            if (Source.DATABASE_TYPE_HIVE.equals(source.getDatabaseType())) {
                                conditionSql.append(key + " <= " + "'" + DateUtils.utcDateStringFormat(list.get(1), "yyyyMMdd") + "'");
                            } else {
                                System.out.println("key:" + "time".equals(key));
                                String endDateString = DateUtils.utcDateStringFormat(list.get(1), "time".equals(key) ? "yyyyMMdd" : "yyyy-MM-dd");
                                endDateString += "time".equals(key) ? "" : " 23:59:59";
                                conditionSql.append(key + " <= " + "'" + endDateString + "'");
                            }
                        } else {
                            if (Source.DATABASE_TYPE_HIVE.equals(source.getDatabaseType())) {
                                conditionSql.append(key + " <= " + "'" + DateUtils.utcDateStringFormat(list.get(1), "yyyyMMdd") + "'");
                            } else {
                                System.out.println("key:" + "time".equals(key));
                                conditionSql.append(key + " <= " + "'" + DateUtils.utcDateStringFormat(list.get(1), "time".equals(key) ? "yyyyMMdd" : "yyyy-MM-dd HH:mm:ss") + "'");
                            }
                        }
                    } else {
                        // 操作符
                        String operator = "=";
                        if (value instanceof String) {
                            operator = "like";
                        }
                        conditionSql.append(key + " " + operator + " " + ("like".equals(operator) ? "'%" + value + "%'" : "'" + value + "'"));
                    }
                }
            }
        }
        System.out.println("--------------------正在执行SQL-------------------------");
        // 判断是否为hive
        if (Source.DATABASE_TYPE_HIVE.equals(source.getDatabaseType())) {
            // hive数据库
            HiveUtils hiveUtils = new HiveUtils(source.getDatabaseUrl(), source.getDatabaseUsername(), source.getDatabasePassword());
            if (conditionSql.length() == 0) {
                conditionSql = new StringBuffer(" where " + "time = '" + DateUtils.getYesterday("yyyyMMdd") + "'");
            }
            ResultSet res = hiveUtils.runSql(sql + conditionSql.toString());
            // 发送user
            int number = 0;
            // 遍历出数据
            List<Map<String, Object>> list = new ArrayList<>();
            while (res.next()) {
                LinkedMap<String, Object> map = new LinkedMap<>(tableConfigColumnList.size());
                for (TableConfigColumn tableConfigColumn : tableConfigColumnList) {
                    // 这里hive会有分区字段，desc会带出来，但是select * from 不会带出来，所以这里捕获异常
                    try {
                        String columnName = tableConfigColumn.getColumnName();
                        map.put(columnName, res.getString(columnName));
                    } catch (SQLException e) {
                    }
                }
                list.add(map);
                number++;
            }
            result.success(list);
            result.setTotal(number);
        } else {
            // 执行sql
            PaginateWithQueryColumns paginateWithQueryColumns = this.sqlUtils.init(new JdbcSourceInfo(source)).executeSql(sql + conditionSql.toString(), current, pageSize);
            // 插入数据
            result.success(paginateWithQueryColumns.getResultList());
            result.setTotal(paginateWithQueryColumns.getTotalCount());
        }
        return result;
    }

}

